#pragma once
#include <sstream>
#include <jsoncpp/json/json.h>

#define SEP "|"
#define SPACE " "
// #define MYSELF

struct Request
{
    int _l;
    int _r;
    char _op;

    Request() {}

    Request(int l, int r, char op)
        : _l(l), _r(r), _op(op)
    {
    }

    std::string Serialize()
    {
#ifdef MYSELF
        std::stringstream oss;
        oss << _l << SPACE << _op << SPACE << _r;
        return oss.str();

#else
        Json::Value root;
        root["l"] = _l;
        root["r"] = _r;
        root["op"] = _op;
        Json::FastWriter writer;
        return writer.write(root);
#endif
    }

    bool Deserialize(const std::string &str)
    {
#ifdef MYSELF
        std::size_t left = str.find(SPACE);
        if (left == std::string::npos)
            return false;
        std::size_t right = str.rfind(SPACE);
        if (right == std::string::npos)
            return false;
        _l = std::stoi(str.substr(0, left));
        _r = std::stoi(str.substr(right + strlen(SPACE)));
        if (left + strlen(SPACE) > str.size())
            return false;
        else
            _op = str[left + strlen(SPACE)];

        return true;
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(str, root);
        _l = root["l"].asInt();
        _r = root["r"].asInt();
        _op = root["op"].asInt();
        return true;
#endif
    }
};

struct Response
{
    int _ret;
    int _code;

    Response() {}

    Response(int ret, int code)
        : _ret(ret), _code(code)
    {
    }

    std::string Serialize()
    {
#ifdef MYSELF
        std::stringstream oss;
        oss << _ret << SPACE << _code;
        return oss.str();
#else
        Json::Value root;
        root["ret"] = _ret;
        root["code"] = _code;
        Json::FastWriter writer;
        return writer.write(root);
#endif
    }

    bool Deserialize(const std::string &str)
    {
#ifdef MYSELF
        std::size_t pos = str.find(SPACE);
        if (pos == std::string::npos)
            return false;
        _ret = std::stoi(str.substr(0, pos));
        _code = std::stoi(str.substr(pos + strlen(SPACE)));
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(str, root);
        _ret = root["ret"].asInt();
        _code = root["code"].asInt();
        return true;
#endif
    }
};

bool Receive(int sock, std::string *out)
{
    char buffer[1024];
    ssize_t s = recv(sock, buffer, sizeof(buffer), 0);
    if (s > 0)
    {
        buffer[s] = 0;
        *out += buffer;
        return true;
    }
    else
    {
        return false;
    }
}

void Send(int sock, const std::string &str)
{
    send(sock, str.c_str(), str.size(), 0);
}

std::string Decode(std::string &buffer)
{
    size_t pos = buffer.find(SEP);
    if (pos == std::string::npos)
        return "";
    int len = std::stoi(buffer.substr(0, pos));
    int content_len = buffer.size() - pos - 2 * strlen(SEP);
    if (content_len >= len)
    {
        buffer.erase(0, pos+strlen(SEP));
        std::string package;
        package = buffer.substr(0, len);
        buffer.erase(0, len+strlen(SEP));
        return package;
    }
    else
    {
        return "";
    }
}

std::string Encode(const std::string &str)
{
    std::stringstream oss;
    //最终格式：
    //response: len|ret code|
    //request: len|l op r|
    oss << std::to_string(str.size()) << SEP << str << SEP;
    return oss.str();
}